package org.entities;

import org.GameState;
import org.BlockMap;
import org.newdawn.slick.Animation;
import org.newdawn.slick.SpriteSheet;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Color;
public class Player extends LevelObject {

    public static final float MOVE_SPEED = 0.05f;                 // player velocity
    private static int size[] = {10, 0, 40, 0, 40, 48, 10, 48};   // player bounding box dimensions
    private float dx = 0;
    private float dy = 0;
    public Animation pleft,              // player going left
             pright,                     // player going right
             pstandleft,                 // player stand facing left
             pstandright,                // player stand facing right
             pdefault,                   // player default anim
             fallback;                   // actually rendered animation
    public String lastFacingDirection;   // remember last facing direction
    public boolean facingLeft,           // player is facing left
             facingRight;                // player is facing right
    
    
    
    public Player(int x, int y, String type) throws SlickException {

        super(x, y,
                // Create dimensions for the player bounding box
                x + size[0], y + size[1],
                x + size[2], y + size[3],
                x + size[4], y + size[5],
                x + size[6], y + size[7],
                type);

        // load player sprite sheet
        SpriteSheet sheet = new SpriteSheet("data/anim/samus.png", 48, 48);

        // create player sprite
        pleft = new Animation();
        for (int frame = 0; frame < 10; frame++) {
            pleft.addFrame(sheet.getSprite(frame, 0), 180);
        }
        pright = new Animation();
        for (int frame = 0; frame < 10; frame++) {
            pright.addFrame(sheet.getSprite(frame, 1), 180);
        }
        pstandleft = new Animation();
        for (int frame = 0; frame < 4; frame++) {
            pstandleft.addFrame(sheet.getSprite(frame, 2), 1080);
        }
        pstandright = new Animation();
        for (int frame = 0; frame < 4; frame++) {
            pstandright.addFrame(sheet.getSprite(frame, 3), 1080);
        }

        pdefault = new Animation();
        for (int frame = 0; frame < 2; frame++) {
            pdefault.addFrame(sheet.getSprite(frame, 6), 180);
        }

        pleft.setAutoUpdate(false);
        pright.setAutoUpdate(false);
        pstandleft.setAutoUpdate(false);
        pstandright.setAutoUpdate(false);
        fallback = pdefault;
    }

    public void update(int delta) throws SlickException {

        fallback = pdefault;
        dx = (float) delta * 2 * MOVE_SPEED;
        dy = (float) delta * 2 * MOVE_SPEED;
        float ax = dx;
        float ay = dy;
        
        
        // check tiles around player for collision 
        // (left,right,up and down of player position) 
        
        //===============
        leftWall.clear();
        //===============
        temp = BlockMap.getBlockAt(((int) x + size[0]) / 16, ((int) y + 2) / 16);
        if (temp != null) {
            leftWall.add(temp);
        }
        temp = BlockMap.getBlockAt(((int) x + size[0]) / 16, ((int) y + 16) / 16);
        if (temp != null) {
            leftWall.add(temp);
        }
        temp = BlockMap.getBlockAt(((int) x + size[0]) / 16, ((int) y + 32) / 16);
        if (temp != null) {
            leftWall.add(temp);
        }
        temp = BlockMap.getBlockAt(((int) x + size[0]) / 16, ((int) y + 45) / 16);
        if (temp != null) {
            leftWall.add(temp);
        }

        //================
        rightWall.clear();
        //================
        temp = BlockMap.getBlockAt(((int) x + size[2]) / 16, ((int) y + 2) / 16);
        if (temp != null) {
            rightWall.add(temp);
        }
        temp = BlockMap.getBlockAt(((int) x + size[2]) / 16, ((int) y + 16) / 16);
        if (temp != null) {
            rightWall.add(temp);
        }
        temp = BlockMap.getBlockAt(((int) x + size[2]) / 16, ((int) y + 32) / 16);
        if (temp != null) {
            rightWall.add(temp);
        }
        temp = BlockMap.getBlockAt(((int) x + size[2]) / 16, ((int) y + 45) / 16);
        if (temp != null) {
            rightWall.add(temp);
        }

        //=============
        upWall.clear();
        //=============
        temp = BlockMap.getBlockAt(((int) x + size[0] + 2) / 16, ((int) y - 5) / 16);
        if (temp != null) {
            upWall.add(temp);
        //System.out.printf("upWall=[%d]\n", upWall.size());
        }
        temp = BlockMap.getBlockAt(((int) x + size[0] + 16) / 16, ((int) y - 5) / 16);
        if (temp != null) {
            upWall.add(temp);
        }
        temp = BlockMap.getBlockAt(((int) x + size[0] + 28) / 16, ((int) y - 5) / 16);
        if (temp != null) {
            upWall.add(temp);
        }

        //===============
        downWall.clear();
        //===============
        temp = BlockMap.getBlockAt(((int) x + size[0] + 2) / 16, ((int) y + size[5]) / 16);
        if (temp != null) {
            downWall.add(temp);
        }
        temp = BlockMap.getBlockAt(((int) x + size[0] + 16) / 16, ((int) y + size[5]) / 16);
        if (temp != null) {
            downWall.add(temp);
        }
        temp = BlockMap.getBlockAt(((int) x + size[0] + 28) / 16, ((int) y + size[5]) / 16);
        if (temp != null) {
            downWall.add(temp);
        }



        // ======================
        // default animation code
        // ======================
        if (facingLeft) {
            fallback = pstandleft;
            pstandleft.update(delta);
        }
        if (facingRight) {
            fallback = pstandright;
            pstandright.update(delta);
        }


        // =====================
        // player goes left
        // =====================
        if (GameState.left) {
            facingRight = false;
            facingLeft = true;
            fallback = pleft;
            pleft.update(delta);

            if (leftWall.size() == 0||diagDown||diagUp) {
                x -= ax;
                poly.setX(x + size[0]);
            }
            if (leftWall.size() > 0) {
                if (leftWall.get(0).type.equals("doorLD")) {
                  //what to do if we bump into a door object ...  
                }
                if (leftWall.get(0).type.equals("dDown")){
                  //diagonal going down \
                    y -= (vec.getY() / 16);
                    poly.setY(y);
                    diagDown=true;
                }else{diagDown=false;}

            }
            if (downWall.size()>1&&downWall.get(1).type.equals("dUp")){
                y += (vec.getY() / 16);
                poly.setY(y);
                diagUp=true;                
            }else{diagUp=false;}

        }

        // =====================
        // player goes right
        // =====================        
        if (GameState.right) {
            facingRight = true;
            facingLeft = false;
            fallback = pright;
            pright.update(delta);

            if (rightWall.size() == 0||diagUp||diagDown) {
                x += ax;
                poly.setX(x + size[0]);
            }

            if (rightWall.size() > 0) {
                if (rightWall.get(0).type.equals("doorRD")) {
                    //what to do if we bump into a door object ...  
                }
                
                if (rightWall.get(0).type.equals("dUp")){
                    //diagonal going up /
                    y-=(vec.getY()/16);                
                    poly.setY(y);
                    diagUp=true;
                }
            }
            if (downWall.size()>1&&downWall.get(1).type.equals("dDown")){
                y += (vec.getY() / 16);
                poly.setY(y);
                diagDown=true;                
            }else{diagDown=false;}
            

        }

        // =====================
        // player goes down
        // =====================        
        if (GameState.down) {

            if (downWall.size() == 0) {
                y += ay;
                poly.setY(y);
            }
        }


        // =====================
        // player goes up
        // =====================        
        if (GameState.up) {
            if (upWall.size() == 0) {
                y -= ay * 2;
                poly.setY(y);
            }
        }


        // ==============
        // gravity code 
        // ==============

        if (downWall.size() == 0) {
            y += ay;
            poly.setY(y);
        }


        // ==============================
        // player don't cross map borders
        // ==============================        
        if (x < 0) {
            x = 0;
        }
        if (y < 0) {
            y = 0;
        }
        if (x > BlockMap.mapWidth - 48) {
            x = BlockMap.mapWidth - 48;
        }
        if (y > BlockMap.mapHeight - 50) {
            y = BlockMap.mapHeight - 50;
        }
    }



    // =====================
    // player render code
    // =====================
    public void draw(Graphics g) {
        
        //debug collision poly
        g.setColor(Color.white);
        g.draw(poly);
        if (upWall.size() > 0) {
            for (int i = 0; i < upWall.size(); i++) {
                g.draw(upWall.get(i).poly);
            }
        }
        if (downWall.size() > 0) {
            for (int i = 0; i < downWall.size(); i++) {
                g.draw(downWall.get(i).poly);
            }
        }
        if (leftWall.size() > 0) {
            for (int i = 0; i < leftWall.size(); i++) {
                g.draw(leftWall.get(i).poly);
            }
        }
        if (rightWall.size() > 0) {
            for (int i = 0; i < rightWall.size(); i++) {
                g.draw(rightWall.get(i).poly);
            }
        }
        g.drawAnimation(fallback, x, y);  
    }
}


